package com.koushikdutta.ion;

import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable.Callback;
import android.os.Looper;
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.animation.Animation;
import android.widget.ImageView;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.async.future.SimpleFuture;
import com.koushikdutta.async.util.FileCache;
import com.koushikdutta.ion.bitmap.BitmapInfo;
import com.koushikdutta.ion.future.ImageViewFuture;
import java.lang.ref.WeakReference;

class IonDrawable extends Drawable {
    private static final double LOG_2 = Math.log(2.0d);
    private IonDrawableCallback callback;
    int currentFrame;
    private boolean disableFadeIn;
    Callback drawableCallback = new Callback() {
        public void invalidateDrawable(Drawable who) {
            IonDrawable.this.invalidateSelf();
        }

        public void scheduleDrawable(Drawable who, Runnable what, long when) {
            IonDrawable.this.scheduleSelf(what, when);
        }

        public void unscheduleDrawable(Drawable who, Runnable what) {
            IonDrawable.this.unscheduleSelf(what);
        }
    };
    private Drawable error;
    private int errorResource;
    private BitmapInfo info;
    private Runnable invalidate = new Runnable() {
        public void run() {
            IonDrawable.this.invalidateScheduled = false;
            IonDrawable ionDrawable = IonDrawable.this;
            ionDrawable.currentFrame++;
            IonDrawable.this.invalidateSelf();
        }
    };
    private boolean invalidateScheduled;
    private Ion ion;
    private int loadedFrom;
    private int maxLevel;
    private Paint paint;
    private Drawable placeholder;
    private int placeholderResource;
    private int resizeHeight;
    private int resizeWidth;
    private Resources resources;
    private int textureDim;
    FutureCallback<BitmapInfo> tileCallback = new FutureCallback<BitmapInfo>() {
        public void onCompleted(Exception e, BitmapInfo result) {
            IonDrawable.this.invalidateSelf();
        }
    };

    public static class ImageViewFutureImpl extends SimpleFuture<ImageView> implements ImageViewFuture {
    }

    static class IonDrawableCallback implements FutureCallback<BitmapInfo> {
        static final /* synthetic */ boolean $assertionsDisabled = (!IonDrawable.class.desiredAssertionStatus());
        private String bitmapKey;
        private ImageViewFutureImpl imageViewFuture = new ImageViewFutureImpl();
        private ImageViewContextReference imageViewRef;
        private Animation inAnimation;
        private int inAnimationResource;
        private WeakReference<IonDrawable> ionDrawableRef;

        public IonDrawableCallback(IonDrawable drawable, ImageView imageView) {
            this.ionDrawableRef = new WeakReference(drawable);
            this.imageViewRef = new ImageViewContextReference(imageView);
        }

        public void onCompleted(Exception e, BitmapInfo result) {
            if (!$assertionsDisabled && Thread.currentThread() != Looper.getMainLooper().getThread()) {
                throw new AssertionError();
            } else if ($assertionsDisabled || result != null) {
                ImageView imageView = (ImageView) this.imageViewRef.get();
                if (imageView != null) {
                    Drawable drawable = (IonDrawable) this.ionDrawableRef.get();
                    if (drawable != null && imageView.getDrawable() == drawable) {
                        imageView.setImageDrawable(null);
                        drawable.setBitmap(result, result.loadedFrom);
                        imageView.setImageDrawable(drawable);
                        IonBitmapRequestBuilder.doAnimation(imageView, this.inAnimation, this.inAnimationResource);
                        if (this.imageViewRef.isAlive() != null) {
                            this.imageViewFuture.cancelSilently();
                        } else {
                            this.imageViewFuture.setComplete(e, imageView);
                        }
                    }
                }
            } else {
                throw new AssertionError();
            }
        }
    }

    public IonDrawable ion(Ion ion) {
        this.ion = ion;
        return this;
    }

    public ImageViewFutureImpl getFuture() {
        return this.callback.imageViewFuture;
    }

    public IonDrawable setDisableFadeIn(boolean disableFadeIn) {
        this.disableFadeIn = disableFadeIn;
        return this;
    }

    public IonDrawable setInAnimation(Animation inAnimation, int inAnimationResource) {
        this.callback.inAnimation = inAnimation;
        this.callback.inAnimationResource = inAnimationResource;
        return this;
    }

    public void cancel() {
        unregister(this.ion, this.callback.bitmapKey, this.callback);
        this.callback.bitmapKey = null;
    }

    private static void unregister(Ion ion, String key, IonDrawableCallback callback) {
        if (key != null) {
            if (ion.bitmapsPending.removeItem(key, callback)) {
                DeferredLoadBitmap owner = ion.bitmapsPending.tag(key);
                if (owner instanceof TransformBitmap) {
                    TransformBitmap info = (TransformBitmap) owner;
                    ion.bitmapsPending.remove(info.key);
                    if (ion.bitmapsPending.removeItem(info.downloadKey, info)) {
                        owner = ion.bitmapsPending.tag(info.downloadKey);
                    }
                }
                if (owner instanceof DeferredLoadBitmap) {
                    ion.bitmapsPending.remove(owner.key);
                }
            }
            ion.processDeferred();
        }
    }

    public void register(Ion ion, String bitmapKey) {
        String previousKey = this.callback.bitmapKey;
        if (!TextUtils.equals(previousKey, bitmapKey)) {
            this.callback.bitmapKey = bitmapKey;
            ion.bitmapsPending.add(bitmapKey, this.callback);
            unregister(ion, previousKey, this.callback);
        }
    }

    public IonDrawable(Resources resources, ImageView imageView) {
        this.resources = resources;
        this.paint = new Paint(6);
        this.callback = new IonDrawableCallback(this, imageView);
    }

    public IonDrawable setBitmap(BitmapInfo info, int loadedFrom) {
        if (this.info != info) {
            cancel();
            this.loadedFrom = loadedFrom;
            this.info = info;
            this.currentFrame = 0;
            this.invalidateScheduled = false;
            invalidateSelf();
            if (info == null) {
                this.callback.bitmapKey = null;
            } else {
                if (info.decoder != null) {
                    this.maxLevel = (int) Math.ceil(Math.log(Math.max(((double) info.originalSize.x) / 256.0d, ((double) info.originalSize.y) / 256.0d)) / LOG_2);
                    this.textureDim = 256 << this.maxLevel;
                }
                this.callback.bitmapKey = info.key;
            }
        }
        return this;
    }

    public IonDrawable setSize(int resizeWidth, int resizeHeight) {
        if (!(this.resizeWidth == resizeWidth && this.resizeHeight == resizeHeight)) {
            this.resizeWidth = resizeWidth;
            this.resizeHeight = resizeHeight;
            invalidateSelf();
        }
        return this;
    }

    public IonDrawable setError(int resource, Drawable drawable) {
        if ((drawable == null || drawable != this.error) && (resource == 0 || resource != this.errorResource)) {
            this.errorResource = resource;
            if (this.error != null) {
                this.error.setCallback(null);
            }
            this.error = drawable;
            invalidateSelf();
        }
        return this;
    }

    public IonDrawable setPlaceholder(int resource, Drawable drawable) {
        if ((drawable == null || drawable != this.placeholder) && (resource == 0 || resource != this.placeholderResource)) {
            this.placeholderResource = resource;
            if (this.placeholder != null) {
                this.placeholder.setCallback(null);
            }
            this.placeholder = drawable;
            invalidateSelf();
        }
        return this;
    }

    public void setFilterBitmap(boolean filter) {
        this.paint.setFilterBitmap(filter);
        invalidateSelf();
    }

    public void setDither(boolean dither) {
        this.paint.setDither(dither);
        invalidateSelf();
    }

    private Drawable tryGetErrorResource() {
        if (this.error != null) {
            return this.error;
        }
        if (this.errorResource == 0) {
            return null;
        }
        this.error = this.resources.getDrawable(this.errorResource);
        this.error.setCallback(this.drawableCallback);
        return this.error;
    }

    private Drawable tryGetPlaceholderResource() {
        if (this.placeholder != null) {
            return this.placeholder;
        }
        if (this.placeholderResource == 0) {
            return null;
        }
        this.placeholder = this.resources.getDrawable(this.placeholderResource);
        this.placeholder.setCallback(this.drawableCallback);
        return this.placeholder;
    }

    public int getIntrinsicWidth() {
        if (this.info != null) {
            if (this.info.decoder != null) {
                return this.info.originalSize.x;
            }
            if (this.info.bitmaps != null) {
                return this.info.bitmaps[0].getScaledWidth(this.resources.getDisplayMetrics().densityDpi);
            }
        }
        if (this.resizeWidth > 0) {
            return this.resizeWidth;
        }
        if (this.info != null) {
            Drawable error = tryGetErrorResource();
            if (error != null) {
                return error.getIntrinsicWidth();
            }
        }
        Drawable placeholder = tryGetPlaceholderResource();
        if (placeholder != null) {
            return placeholder.getIntrinsicWidth();
        }
        return -1;
    }

    public int getIntrinsicHeight() {
        if (this.info != null) {
            if (this.info.decoder != null) {
                return this.info.originalSize.y;
            }
            if (this.info.bitmaps != null) {
                return this.info.bitmaps[0].getScaledHeight(this.resources.getDisplayMetrics().densityDpi);
            }
        }
        if (this.resizeHeight > 0) {
            return this.resizeHeight;
        }
        if (this.info != null) {
            Drawable error = tryGetErrorResource();
            if (error != null) {
                return error.getIntrinsicHeight();
            }
        }
        Drawable placeholder = tryGetPlaceholderResource();
        if (placeholder != null) {
            return placeholder.getIntrinsicHeight();
        }
        return -1;
    }

    private void drawDrawable(Canvas canvas, Drawable d) {
        if (d != null) {
            d.setBounds(getBounds());
            d.draw(canvas);
        }
    }

    public void draw(Canvas canvas) {
        if (this.info == null) {
            drawDrawable(canvas, tryGetPlaceholderResource());
            return;
        }
        if (this.info.drawTime == 0) {
            this.info.drawTime = SystemClock.uptimeMillis();
        }
        long destAlpha = 255;
        if (!this.disableFadeIn) {
            destAlpha = Math.min(((SystemClock.uptimeMillis() - this.info.drawTime) << 8) / 200, 255);
        }
        if (destAlpha != 255) {
            Drawable placeholder = tryGetPlaceholderResource();
            if (placeholder != null) {
                drawDrawable(canvas, placeholder);
            }
        }
        if (this.info.decoder != null) {
            Rect clip = canvas.getClipBounds();
            Rect bounds = getBounds();
            float zoom = ((float) canvas.getWidth()) / ((float) clip.width());
            double wlevel = Math.log((double) ((zoom * ((float) bounds.width())) / 256.0f)) / LOG_2;
            double maxLevel = Math.max(wlevel, Math.log((double) ((zoom * ((float) bounds.height())) / 256.0f)) / LOG_2);
            int visibleLeft = Math.max(0, clip.left);
            int visibleRight = Math.min(bounds.width(), clip.right);
            int visibleTop = Math.max(0, clip.top);
            int visibleBottom = Math.min(bounds.height(), clip.bottom);
            int level = Math.max(Math.min(this.maxLevel, (int) Math.floor(maxLevel)), 0);
            int levelTiles = 1 << level;
            int textureTileDim = this.textureDim / levelTiles;
            if (this.info.bitmaps == null || this.info.bitmaps[0] == null) {
                this.paint.setColor(-16777216);
                canvas.drawRect(getBounds(), this.paint);
            } else {
                canvas.drawBitmap(this.info.bitmaps[0], null, getBounds(), this.paint);
            }
            int sampleSize = 1;
            while (textureTileDim / sampleSize > 256) {
                sampleSize <<= 1;
            }
            for (int y = 0; y < levelTiles; y++) {
                int top = textureTileDim * y;
                int bottom = Math.min(textureTileDim * (y + 1), bounds.bottom);
                if (bottom >= visibleTop) {
                    if (top > visibleBottom) {
                        break;
                    }
                    for (int x = 0; x < levelTiles; x++) {
                        int left = textureTileDim * x;
                        int right = Math.min(textureTileDim * (x + 1), bounds.right);
                        if (right >= visibleLeft) {
                            if (left > visibleRight) {
                                break;
                            }
                            Rect texRect = new Rect(left, top, right, bottom);
                            String tileKey = FileCache.toKeyString(this.info.key, ",", Integer.valueOf(level), ",", Integer.valueOf(x), ",", Integer.valueOf(y));
                            BitmapInfo tile = this.ion.bitmapCache.get(tileKey);
                            if (tile == null || tile.bitmaps == null) {
                                if (this.ion.bitmapsPending.tag(tileKey) == null) {
                                    LoadBitmapRegion loadBitmapRegion = new LoadBitmapRegion(this.ion, tileKey, this.info.decoder, texRect, sampleSize);
                                }
                                this.ion.bitmapsPending.add(tileKey, this.tileCallback);
                                int parentLeft = 0;
                                int parentTop = 0;
                                int parentUp = 1;
                                int parentLevel = level - 1;
                                if (x % 2 == 1) {
                                    parentLeft = 0 + 1;
                                }
                                if (y % 2 == 1) {
                                    parentTop = 0 + 1;
                                }
                                int parentX = x >> 1;
                                int parentY = y >> 1;
                                while (parentLevel >= 0) {
                                    tile = this.ion.bitmapCache.get(FileCache.toKeyString(this.info.key, ",", Integer.valueOf(parentLevel), ",", Integer.valueOf(parentX), ",", Integer.valueOf(parentY)));
                                    if (tile != null && tile.bitmaps != null) {
                                        break;
                                    }
                                    if (parentX % 2 == 1) {
                                        parentLeft += 1 << parentUp;
                                    }
                                    if (parentY % 2 == 1) {
                                        parentTop += 1 << parentUp;
                                    }
                                    parentLevel--;
                                    parentUp++;
                                    parentX >>= 1;
                                    parentY >>= 1;
                                }
                                if (!(tile == null || tile.bitmaps == null)) {
                                    int subtileDim = this.textureDim / (1 << parentLevel);
                                    int subSampleSize = 1;
                                    while (subtileDim / subSampleSize > 256) {
                                        subSampleSize <<= 1;
                                    }
                                    int subTextureDim = (subtileDim / subSampleSize) >> parentUp;
                                    int sourceLeft = subTextureDim * parentLeft;
                                    int sourceTop = subTextureDim * parentTop;
                                    Rect rect = new Rect(sourceLeft, sourceTop, sourceLeft + subTextureDim, sourceTop + subTextureDim);
                                    canvas.drawBitmap(tile.bitmaps[0], rect, texRect, this.paint);
                                }
                            } else {
                                canvas.drawBitmap(tile.bitmaps[0], null, texRect, this.paint);
                            }
                        }
                    }
                }
            }
        } else if (this.info.bitmaps != null) {
            this.paint.setAlpha((int) destAlpha);
            canvas.drawBitmap(this.info.bitmaps[this.currentFrame % this.info.bitmaps.length], null, getBounds(), this.paint);
            this.paint.setAlpha(255);
            if (this.info.delays != null) {
                int delay = this.info.delays[this.currentFrame % this.info.delays.length];
                if (!this.invalidateScheduled) {
                    this.invalidateScheduled = true;
                    unscheduleSelf(this.invalidate);
                    scheduleSelf(this.invalidate, SystemClock.uptimeMillis() + ((long) Math.max(delay, 100)));
                }
            }
        } else {
            Drawable error = tryGetErrorResource();
            if (error != null) {
                error.setAlpha((int) destAlpha);
                drawDrawable(canvas, error);
                error.setAlpha(255);
            }
        }
        if (destAlpha != 255) {
            invalidateSelf();
        }
    }

    public void setAlpha(int alpha) {
        this.paint.setAlpha(alpha);
    }

    public void setColorFilter(ColorFilter cf) {
        this.paint.setColorFilter(cf);
    }

    public int getOpacity() {
        return (this.info == null || this.info.bitmaps == null || this.info.bitmaps[0].hasAlpha() || this.paint.getAlpha() < 255) ? -3 : -1;
    }

    static IonDrawable getOrCreateIonDrawable(ImageView imageView) {
        IonDrawable ret;
        Drawable current = imageView.getDrawable();
        if (current == null || !(current instanceof IonDrawable)) {
            ret = new IonDrawable(imageView.getResources(), imageView);
        } else {
            ret = (IonDrawable) current;
        }
        imageView.setImageDrawable(null);
        return ret;
    }
}
